package com.feihong.yw189.bluetooth.utils.djlm.newDJMLReader;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.feihong.yw189.app.App;
import com.feihong.yw189.bluetooth.server.BLEService;
import com.feihong.yw189.bluetooth.utils.util.BmpDecrypt;
import com.feihong.yw189.bluetooth.utils.util.IDCardReadCtrl;
import com.inuker.bluetooth.library.Constants;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.connect.response.BleConnectResponse;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.utils.BluetoothUtils;
import com.kaer.sdk.bt.BtReadClient;
import com.kaeridcard.tools.Tool;
import com.lzw.qlhs.Wlt2bmp;

import org.json.JSONObject;
import org.xutils.http.RequestParams;
import org.xutils.x;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.UUID;


/**
 * 店家联盟阅读器 身份证阅读  萨比尔江 2017-06-08
 */

public class DJLM_CardReader {

    /**
     * 1、连接蓝牙
     * 2、请求通道
     * 3、创建trans通道，网络连接，trans线程，负责COS指令的透明传输。
     * 4、创建后台加速器，预执行可以提前执行的命令。
     * 5、发送寻卡命令
     * 6、发送选卡命令
     * 7、发送读取信息的命令。
     * 8、获得信息后，释放通道
     * 9、照片解码。
     */
    public static final UUID CCCD = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    public static final UUID RX_SERVICE_UUID = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");
    public static final UUID TX_CHAR_UUID = UUID.fromString("0000fff4-0000-1000-8000-00805f9b34fb");
    public static final UUID RX_CHAR6_UUID = UUID.fromString("0000fff6-0000-1000-8000-00805f9b34fb");
    public static final UUID RX_CHAR7_UUID = UUID.fromString("0000fff7-0000-1000-8000-00805f9b34fb");

    private static BtReadClient mClient;
    private static final String TAG = "店家联盟蓝牙";
    public DJLM_ReaderCallBack mCallBack;

    private BluetoothDevice device;
    private Context mContext;

    String strIP, strToken, strBmpURL;
    String strAccelerate;
    int nCardReaderPort, nTransPort;
    boolean bUDP = true;
    DJML_IDCardReaderBase mDJMLIDCardReaderBase = null;
    DJLM_FrameTrans DJLMFrameTrans = null;
    private String macAddress = "";
    private String ServerAddress = "";
    private DJLM_BLEService mService = null;
    private DJLM_CardDeviceIO mDJLMCardDeviceIO = null;
    private long timeStart = 0;
    DJLM_AccelerateCache accelerateCache = null;
    DJLM_FrameTrans frameTrans = null;
    DJML_IDCardReaderBase idCardReaderBase = null;

    public DJLM_CardReader(Context context, String allocAddress, String strmacAddress, DJLM_ReaderCallBack callBack) throws Exception {
        timeStart = System.currentTimeMillis();
        this.ServerAddress = allocAddress;
        this.mContext = context;
        this.mCallBack = callBack;
        mDJMLIDCardReaderBase = new DJML_IDCardReaderBase(context);
        macAddress = strmacAddress;
        this.device = BluetoothUtils.getRemoteDevice(macAddress);

        DJLMFrameTrans = new DJLM_FrameTrans();
        mService = DJLM_BLEService.GetBLEService(mContext);
        mDJLMCardDeviceIO = DJLM_CardDeviceIO.GetCardDeviceIO();
        mService.SetSilence(false); // 取消通知
        if (!mService.initialize()) {
            if (mCallBack != null) {
                mCallBack.readDataError("无法初始化蓝牙服务！");
            }
            disconnect();
            return;
        }
        // mService.connect(macAddress);
        BleConnectOptions options = new BleConnectOptions.Builder()
                .setConnectRetry(3)   // 连接如果失败重试3次
                .setConnectTimeout(10000)   // 连接超时30s
                .setServiceDiscoverRetry(3)  // 发现服务如果失败重试3次
                .setServiceDiscoverTimeout(10000)  // 发现服务超时20s
                .build();
        App.getApp().getmClinet().connect(macAddress, options, new BleConnectResponse() {
            @Override
            public void onResponse(int code, BleGattProfile data) {
                if (code == Constants.REQUEST_SUCCESS) {
                    boolean connect = mService.connect(macAddress, DJLM_CardReader.this.device);
                    if (connect) {
                        mService.WaiteBLEConnnect(3000, 500, connectHandler);
                    } else {
                        if (mCallBack != null) {
                            disconnect();
                            Log.e(TAG, "DJLM_CardReader2:无法初始化蓝牙服务！");
                            mCallBack.readDataError("无法初始化蓝牙服务！");
                        }
                    }
                } else {
                    if (mCallBack != null) {
                        disconnect();
                        Log.e(TAG, "DJLM_CardReader3:无法初始化蓝牙服务！");
                        mCallBack.readDataError("无法连接蓝牙设备！");
                    }
                }
            }
        });
    }

    private Handler connectHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Log.i(TAG, "handleMessage: 来到这里了");
            switch (msg.what) {
                case 0: {
                    if (mCallBack != null) {
                        mCallBack.readDataError("蓝牙连接失败!");
                    }
                    disconnect();
                    mDJLMCardDeviceIO.UninitDevice(true);
                }
                break;
                case 1: {
                    mDJLMCardDeviceIO.InitDevice(mService, null, null, DJLM_CardDeviceIO.DEVICETYPE_BLE);
                    retCount = 2;
                    duquShuJu();
                }
                break;
            }
        }
    };

    DJLM_IDCardBaseInfo DJLMIdCardBaseInfo;
    String strResultInfo = "";
    String strErrorInfo = "";
    String strWLTBase64 = "";

    long span = 0;
    int retCount = 2;

    private void duquShuJu() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    int dianliang = 1000;
                    // 第一步 高低速切换  身份证阅读切换高速
                    float ver = DJML_SIMCard.GetVerFloat(mService);
                    Log.e(TAG, "------高低速模式ver------" + ver);
                    try {
                        if (ver >= 1.028) {//大于1.028版本的板子才能获取高低速状态
                            int ret = 5;
                            boolean isSuccess = false;
                            while (ret > 0) {
                                try {
                                    DJML_SIMCard.BLEFast(mService, true);
                                    DJML_SIMCard.BLEFast(mService, true);
                                } catch (Exception ex) {
                                }
                                int nRetInterval = DJML_SIMCard.GetInterval(mService);
                                Log.e(TAG, "run: 高低速模式：" + nRetInterval + " ret = " + ret);
                                if (nRetInterval <= 20) { //大于20表示低速 ，小于20表示高速
                                    isSuccess = true;
                                    break;
                                }
                                ret--;
                            }
                            if (!isSuccess) {
                                Message message = new Message();
                                message.obj = "蓝牙设备无法切换高速模式，请重启试一试！";
                                message.what = -1;
                                mHandler.sendMessage(message);
                                DJML_SIMCard.PowerOff(mService);//关机设备
                                disconnect();
                                return;
                            }

                            dianliang = DJML_SIMCard.GetBattery(mService);
                            Log.e(TAG, "run: 当前的电量：" + dianliang);
                        } else {//否则多次调用切换低速模式

                            try {
                                DJML_SIMCard.BLEFast(mService, true);
                                DJML_SIMCard.BLEFast(mService, true);
                            } catch (Exception ex) {
                            }
                            try {
                                DJML_SIMCard.BLEFast(mService, true);
                                DJML_SIMCard.BLEFast(mService, true);
                            } catch (Exception ex) {
                            }
                        }

                    } catch (Exception ex) {
                        try {
                            DJML_SIMCard.BLEFast(mService, true);
                            DJML_SIMCard.BLEFast(mService, true);
                            DJML_SIMCard.BLEFast(mService, true);
                            DJML_SIMCard.BLEFast(mService, true);
                        } catch (Exception e) {
                        }
                    }

                    // 第二步 获取网络端信息  readerPort 和 transPort
                    String json = getIPAddress("V" + ver);
                    if (json == null) {
                        try {
                            Thread.sleep(1000);
                        } catch (Exception ex) {

                        }
                        json = getIPAddress("V" + ver);
                        if (json == null) {
                            Message message = new Message();
                            message.obj = "获取服务端失败!";
                            message.what = -1;
                            mHandler.sendMessage(message);
                            Log.e(TAG, "run:获取服务端失败! ");
                            return;
                        }
                    }
                    Log.e(TAG, "duquShuJu: " + json);
                    JSONObject jsonObj = new JSONObject(json);
                    strIP = jsonObj.getString("ip");
                    nCardReaderPort = jsonObj.getInt("ReaderPort");
                    nTransPort = jsonObj.getInt("TransPort");
                    strToken = jsonObj.getString("token");
                    strBmpURL = jsonObj.getString("bmpServer");
                    String strProtocol = jsonObj.getString("Protocol");
                    if (strProtocol.equals("TCP"))
                        bUDP = false;
                    strAccelerate = jsonObj.getString("Accelerate");
                    // 第三段开始 阅读身份证
                    // m_cacheData =  DJML_CommandItem.InitCommandList(m_commandList);
                    DJLMIdCardBaseInfo = ReadCardRemote(mContext, mDJLMCardDeviceIO, strIP, nCardReaderPort, nTransPort, bUDP, strAccelerate, 30000);
                    if (DJLMIdCardBaseInfo != null) {
                        strResultInfo = DJLMIdCardBaseInfo.GetResultText();
                        strErrorInfo = DJLMIdCardBaseInfo.GetErrorInfo();
                        strWLTBase64 = DJLMIdCardBaseInfo.GetWLTBase64();
                    }

                    // 阅读信息上传
                    fanhuizhuangtai();

                    // 处理结果

                    Message message = new Message();
                    int m_nErrorCode = DJLMIdCardBaseInfo.m_nErrorCode;
                    if (m_nErrorCode == 0) {
                        DJML_SIMCard.Beep(mService);
                        long endtime = System.currentTimeMillis();
                        span = endtime - timeStart;
                        Log.e(TAG, "run: 总花了" + (span / 1000) + " 秒 ");
                        Log.e(TAG, "run: 代码结束.............................." + strErrorInfo + " ");
                        Log.e(TAG, "run: 代码结束.............................." + strResultInfo + " ");
                        message.obj = strResultInfo;
                        message.what = 1;
                        mHandler.sendMessage(message);
                        try {
                            // 图片解密，先用卡尔的本地解码，如果本地解码失败，再用服务器解码...
                            Bitmap bitmap = null;
                            if (strBmpURL != null) {
                                try {
                                    byte[] images = DJLMIdCardBaseInfo.GetWLTByte();
                                    bitmap = getPicBitmap(images);
                                    if (bitmap != null) {
                                        Log.e(TAG, "run:解码图片成功");
                                        message = new Message();
                                        message.obj = bitmap;
                                        message.what = 2;
                                        mHandler.sendMessage(message);
                                    } else {
                                        Log.e(TAG, "run: 本地解码失败！");
                                    }
                                } catch (Exception ex) {
                                    Log.e(TAG, "run: 解析图片失败！" + ex.getMessage());
                                    ex.printStackTrace();
                                    bitmap = BmpDecrypt.BmpDecryptRemote(strBmpURL, macAddress, strToken, strWLTBase64);
                                    if (bitmap != null) {
                                        message = new Message();
                                        message.obj = bitmap;
                                        message.what = 2;
                                        mHandler.sendMessage(message);
                                    } else {
                                        Log.e(TAG, "run: 无法获取解码的图片");
                                        message = new Message();
                                        message.obj = "无法获取解码的图片";
                                        message.what = -2;
                                        mHandler.sendMessage(message);
                                    }
                                }
                            } else {
                                Log.e(TAG, "run: 图片解析失败！服务器解码地址空");
                                message = new Message();
                                message.obj = "图片解析失败！服务器解码地址空";
                                message.what = -2;
                                mHandler.sendMessage(message);
                            }
                        } catch (Exception ex) {
                            Log.e(TAG, "run: " + ex.getMessage());
                            message = new Message();
                            message.obj = "图片解析失败！";
                            message.what = -2;
                            mHandler.sendMessage(message);
                        }


                    } else {
                        String msg = "读取数据失败，身份证放好后请重试！";
                        if (dianliang < 400) {
                            msg = "读取失败，当前设备的电量比较低，请充电再试！";
                        }
                        message.obj = msg;
                        message.what = -1;
                        mHandler.sendMessage(message);
                    }
                } catch (Exception throwable) {
                    Log.e(TAG, "run: 代码异常结束..............................");
                    throwable.printStackTrace();
                    Message message = new Message();
                    message.obj = "读取数据失败，身份证放好后请重试！";
                    message.what = -1;
                    mHandler.sendMessage(message);
                    Log.e(TAG, "run: " + throwable.getLocalizedMessage());
                }
                disconnect();
            }
        }).start();
    }

    private void fanhuizhuangtai() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if (strIP != null && strToken != null) {
                        String allocURL = ServerAddress;
                        if (!allocURL.endsWith("/"))
                            allocURL += "/";
                        allocURL += "channel_free";
                        String strParams = "";
                        try {
                            strParams += "Token=" + URLEncoder.encode(strToken, "utf-8");
                            if (strErrorInfo == null || strErrorInfo.trim().length() == 0) {
                                strErrorInfo = "OK";
                            }
                            strParams += "&Result=" + URLEncoder.encode(strErrorInfo, "utf-8");
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                        BmpDecrypt.RequestToUrl(allocURL + "?" + strParams, "GET", null);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }).start();
    }

    private Bitmap getPicBitmap(byte[] pic_src) {
        int HEAD_LEN = 306;
        int BMP_LEN = 38556;

        byte[] tmp_data = new byte[40960];
        int result = Wlt2bmp.picUnpack(pic_src, tmp_data);
        if (result != 1) {
            return null;
        }
        byte[] bmp_data = new byte[38556];
        System.arraycopy(tmp_data, 0, bmp_data, 0, 38556);
        return Tool.createRgbBitmap(bmp_data, 102, 126);
    }

    private Bitmap picDecode(byte[] card_data) {
        return getPicBitmap(card_data);
    }

    //加载卡尔的静态库
    static {
        try {
            System.loadLibrary("wlt920bmp");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == -1) {
                if (mCallBack != null) {
                    mCallBack.readDataError(msg.obj.toString());
                }
            } else if (msg.what == 1) {
                if (mCallBack != null) {
                    mCallBack.readData(msg.obj.toString());
                }
            } else if (msg.what == 2) {
                if (mCallBack != null) {
                    Bitmap bitmap = (Bitmap) msg.obj;
                    mCallBack.parseBitmapSuccess(bitmap);
                }
            } else if (msg.what == -2) {
                if (mCallBack != null) {
                    mCallBack.parseBitmapError(msg.obj.toString());
                }
            } else if (msg.what == -3) {
                //  Toast.makeText(mContext, msg.obj.toString(), Toast.LENGTH_SHORT).show();
            }
        }
    };

    public DJLM_IDCardBaseInfo ReadCardRemote(Context ctx, DJLM_CardDeviceIO mDJLMCardDeviceIO, String strIP, int nCardReaderPort, int nTransPort, boolean bUDP, String strAccelerate, int nWaiteTime) {

        int nRet = 1;
        DJLM_IDCardBaseInfo idCardBaseInfo = new DJLM_IDCardBaseInfo();
        accelerateCache = new DJLM_AccelerateCache(false, strAccelerate, 10000);
        accelerateCache.SetTransChannel(mDJLMCardDeviceIO);
        accelerateCache.Start();
        idCardReaderBase = new DJML_IDCardReaderBase(ctx);
        try {
            idCardReaderBase.InitConnect(strIP, nCardReaderPort, bUDP);
        } catch (IOException e) {
            e.printStackTrace();
        }
        frameTrans = new DJLM_FrameTrans();
        frameTrans.StartTrans(mDJLMCardDeviceIO, accelerateCache, strIP, nTransPort, bUDP, idCardReaderBase.m_ErrHandler);
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 3 && nRet != 0; i++) {
            Log.e(TAG, "ReadCardRemote: 正在测试:" + (i + 1) + " 阶段！");
            byte[] SW = new byte[3];
            byte[] iDCardData = new byte[4 + 256 + 1024];
            try {
                nRet = idCardReaderBase.ReadCardOneCard(iDCardData, SW, nWaiteTime);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                idCardBaseInfo.m_strErrorInfo = e.getMessage();
                e.printStackTrace();
            }
            if (nRet == 0) {
                idCardBaseInfo.m_data = iDCardData;
                idCardBaseInfo.m_strErrorInfo = "OK";
            }
            idCardBaseInfo.m_SW = SW;
            idCardBaseInfo.m_nErrorCode = nRet;
            if (nRet == 0) {
                Log.e(TAG, "ReadCardRemote: 正在测试:" + (i + 1) + " 阶段！读取成功...");
                mDJLMCardDeviceIO.Beep();
            } else {
                Log.e(TAG, "ReadCardRemote: 正在测试:" + (i + 1) + " 阶段！读取失败..." + idCardBaseInfo.m_strErrorInfo);
                Message message = new Message();
                message.obj = "竖直放身份证并紧贴指示灯！";
                message.what = -3;
                mHandler.sendMessage(message);
                accelerateCache.InitCache();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        {
            accelerateCache.Stop();
            idCardReaderBase.CloseConnect();
            frameTrans.StopTrans();
        }
        try {
            accelerateCache = null;
            idCardReaderBase = null;
            frameTrans = null;
        } catch (Exception ex) {

        }
        return idCardBaseInfo;
    }

    private String getIPAddress(String ver) {
        try {
            String strCientSN = "";
            String strClientVer = "";
            String strUser = "";
            String strPWD = "";
            ///////////////////////
            //////////////////////
            String strResultInfo = null;
            {
                strCientSN = macAddress;
                strClientVer = ver; //mDJLMCardDeviceIO.GetDeviceVer();
            }
            if (strClientVer == null || strCientSN == null) {
                strResultInfo = "get version error!";
                ServerAddress = null;
            }
            if (ServerAddress != null) {
                System.out.println("Alloc Channel!");
                String allocURL = ServerAddress;
                if (!allocURL.endsWith("/"))
                    allocURL += "/";
                allocURL += "channel_alloc";
//                allocURL = "http://60.13.131.22:8090/MutexComm/channel_alloc";
                String strNetworkType = IDCardReadCtrl.GetNetworkType(mContext);
                String strSystemInfo = IDCardReadCtrl.GetSystemInfo(mContext);
                String strDeviceType = mDJLMCardDeviceIO.GetDeviceType();
                try {
                    strCientSN = URLEncoder.encode(strCientSN, "utf-8");
                    if (strClientVer != null)
                        strClientVer = URLEncoder.encode(strClientVer, "utf-8");
                    strUser = URLEncoder.encode(strUser, "utf-8");
                    strPWD = URLEncoder.encode(strPWD, "utf-8");
                    ///////////////////////////////////////
                    strNetworkType = URLEncoder.encode(strNetworkType, "utf-8");
                    strSystemInfo = URLEncoder.encode(strSystemInfo, "utf-8");
                    strDeviceType = URLEncoder.encode(strDeviceType, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                String strParams = "ClientSN=" + strCientSN
                        + "&ClientVer=" + strClientVer
                        + "&User=" + strUser
                        + "&Password=" + strPWD
                        + "&OverTime=" + 0
                        + "&HostType=AndroidMobile"
                        + "&NetworkType=" + strNetworkType
                        + "&SystemInfo=" + strSystemInfo
                        + "&DeviceType=" + strDeviceType;

                RequestParams requestParams = new RequestParams(allocURL + "?" + strParams);
                String string = x.http().getSync(requestParams,String.class);
                return string;
            }
        } catch (Exception ex) {

        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;

    }

    public void disconnect() {
        try {
            if (mService != null) {
                mService.disconnect();
            }
            if (frameTrans != null) {
                frameTrans.StopTrans();
            }
            if (accelerateCache != null) {
                accelerateCache.Stop();
            }
            if (idCardReaderBase != null) {
                idCardReaderBase.CloseConnect();
            }
            Log.e(TAG, "disconnect: ==========蓝牙操作已结束....释放连接成功。。。。");
            if (mService != null) {
                mService.disconnect();
            }
            App.getApp().getmClinet().disconnect(macAddress);
            App.getApp().getmClinet().disconnect(macAddress);

            BLEService.g_BLEService = null;
        } catch (Exception ex) {
            Log.e(TAG, "disconnect: ==========蓝牙操作已结束....释放连接失败。。。。");
            ex.printStackTrace();
        }
    }
}
